from __future__ import absolute_import, division, print_function, unicode_literals

# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras

# Helper libraries
import numpy as np
import matplotlib.pyplot as plt

# 设置中文显示，防止中文显示乱码
from pylab import mpl

mpl.rcParams['font.sans-serif'] = ['FangSong']  # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

# 加载数据集
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

# 以下用于创建模型

# 下面的代码很显然存在三层,
# 其中第一层是tf.keras.layers.Flatten(),主要的功能就是将(28,28)像素的图像即对应的2维的数组转成28*28=784的一维的数组.
# 第二层是Dense,如果你上过吴恩达的课程,或者有一点机器学习的基础的话,这个可以理解成全连接层,这个层存在128的神经元.
# 最后一层是softmax层,它返回的是由10个概率值(加起来等于1)组成的1维数组,每一个代表了这个图像属于某个类别的概率.
model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])

# 每个图像都映射到一个标签
class_names = ['T恤/上衣', '裤子', '套衫', '连衣裙', '外套',
               '凉鞋', '衬衫', '运动鞋', '包/袋', '脚踝靴']

def buildModel():
    # 图像归一化
    # 将矩阵存储的整数（0，255）归一化到（0，1）的浮点数
    global train_images
    global test_images
    train_images = train_images / 255.0
    test_images = test_images / 255.0

    # 创建一个10x10大小的窗口
    plt.figure(figsize=(10, 10))
    for i in range(25):
        plt.subplot(5, 5, i + 1)  # 5行5列，放到第i+1个位置，起始位置索引为1，即1<=index<=nrows*ncols
        plt.xticks([])  # 传递空标签禁用x轴
        plt.yticks([])  # 传递空标签禁用y轴
        plt.grid(False)  # 设置网格线
        plt.imshow(train_images[i], cmap=plt.cm.binary)  # 设置图像显示方式为二值
        plt.xlabel(class_names[train_labels[i]])  # 设置每个图片的下标
    plt.show()  # 显示一个图表

    # 以下用于创建模型

    global model
    # 以下用于编译模型

    # 优化器是AdamOptimizer(表示采用何种方式寻找最佳答案,有什么梯度下降啊等等),
    # 损失函数是sparse_categorical_crossentropy(就是损失函数怎么定义的,最佳值就是使得损失函数最小).
    # 计量标准是准确率,也就是正确归类的图像的概率.
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

    # 调用函数开始训练，epochs指定训练次数
    model.fit(train_images, train_labels, epochs=1)

    # 在测试集上完成准确率的评估,
    test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
    print('\nTest accuracy:', test_acc)  # 输出准确率


def plot_image(i, predictions_array, true_label, img):
    global class_names
    predictions_array, true_label, img = predictions_array, true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'
    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                         100 * np.max(predictions_array),
                                         class_names[true_label]),color=color)


def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array, true_label[i]
    plt.grid(False)
    plt.xticks(range(10))
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')


def prediction():
    global test_images
    # 进行预测
    predictions = model.predict(test_images)
    num_rows = 5
    num_cols = 3
    num_images = num_rows * num_cols
    plt.figure(figsize=( 2*num_cols, num_rows))
    for i in range(num_images):
        plt.subplot(num_rows, 2 * num_cols, 2 * i+1)
        plot_image(i, predictions[i], test_labels, test_images) #显示图片
    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    buildModel()
    prediction()
